import sys
import math
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, 
                             QWidget, QLabel, QComboBox, QPushButton, QTextEdit,
                             QGraphicsView, QGraphicsScene, QGraphicsItem, QGraphicsEllipseItem,
                             QGraphicsLineItem, QGraphicsTextItem)
from PyQt5.QtCore import Qt, QPointF
from PyQt5.QtGui import QFont, QPen, QBrush, QColor, QPainter


class CampusMap:
    def __init__(self):
        # 位置信息：名称 -> (x, y) 坐标
        self.locations = {
            "大门": (100, 300),
            "计通楼": (300, 200),
            "南苑食堂": (500, 400),
            "崇礼楼": (700, 250),
            "图书馆": (400, 100),
            "体育馆": (600, 500)
        }
        
        # 连接信息：位置 -> [连接的位置]
        self.connections = {
            "大门": ["计通楼", "南苑食堂"],
            "计通楼": ["大门", "图书馆", "南苑食堂"],
            "南苑食堂": ["大门", "计通楼", "体育馆"],
            "崇礼楼": ["图书馆", "体育馆"],
            "图书馆": ["计通楼", "崇礼楼"],
            "体育馆": ["南苑食堂", "崇礼楼"]
        }
        
        # 位置功能描述
        self.functions = {
            "大门": ["校园入口", "安保服务"],
            "计通楼": ["计算机与通信学院", "实验室", "办公室"],
            "南苑食堂": ["领军训服", "领床铺用品", "餐饮服务"],
            "崇礼楼": ["材料工程学院", "实验室", "办公室"],
            "图书馆": ["借阅图书", "自习室", "电子资源"],
            "体育馆": ["体育课", "健身", "运动器材"]
        }
        
        # 路径描述
        self.path_descriptions = {
            ("大门", "计通楼"): "直走100米到达",
            ("大门", "南苑食堂"): "右转走150米到达",
            ("计通楼", "图书馆"): "上楼走50米到达",
            ("计通楼", "南苑食堂"): "下楼左转走80米到达",
            ("南苑食堂", "体育馆"): "直走120米到达",
            ("图书馆", "崇礼楼"): "穿过走廊走90米到达",
            ("崇礼楼", "体育馆"): "下楼右转走110米到达"
        }
    
    def get_all_locations(self):
        """获取所有位置名称"""
        return list(self.locations.keys())
    
    def get_location_functions(self, location):
        """获取指定位置的功能"""
        return self.functions.get(location, [])
    
    def find_shortest_path(self, start, end):
        """使用BFS算法找到最短路径"""
        if start == end:
            return [start]
        
        visited = set()
        queue = [(start, [start])]
        
        while queue:
            current_location, path = queue.pop(0)
            
            if current_location == end:
                return path
            
            if current_location not in visited:
                visited.add(current_location)
                
                for neighbor in self.connections.get(current_location, []):
                    if neighbor not in visited:
                        queue.append((neighbor, path + [neighbor]))
        
        return None
    
    def get_path_description(self, path):
        """根据路径生成描述"""
        if len(path) < 2:
            return "已经在目的地"
        
        description = f"从 {path[0]} 出发：\n"
        for i in range(len(path) - 1):
            from_loc = path[i]
            to_loc = path[i + 1]
            step_desc = self.path_descriptions.get((from_loc, to_loc), 
                                                 self.path_descriptions.get((to_loc, from_loc), 
                                                                          f"前往 {to_loc}"))
            description += f"{i+1}. {step_desc}\n"
        
        description += f"到达目的地：{path[-1]}"
        return description


class MapGraphicsView(QGraphicsView):
    def __init__(self, campus_map):
        super().__init__()
        self.campus_map = campus_map
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self.setRenderHint(QPainter.Antialiasing)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        
        # 设置场景大小
        self.scene.setSceneRect(0, 0, 800, 600)
        self.draw_map()
    
    def draw_map(self):
        """绘制地图"""
        self.scene.clear()
        
        # 绘制连接线
        pen = QPen(QColor(100, 100, 100), 2)
        for location, neighbors in self.campus_map.connections.items():
            start_pos = QPointF(*self.campus_map.locations[location])
            for neighbor in neighbors:
                end_pos = QPointF(*self.campus_map.locations[neighbor])
                line = QGraphicsLineItem(start_pos.x(), start_pos.y(), end_pos.x(), end_pos.y())
                line.setPen(pen)
                self.scene.addItem(line)
        
        # 绘制位置点
        for location, (x, y) in self.campus_map.locations.items():
            # 绘制圆形节点
            ellipse = QGraphicsEllipseItem(x-15, y-15, 30, 30)
            ellipse.setBrush(QBrush(QColor(70, 130, 180)))
            ellipse.setPen(QPen(QColor(30, 90, 140), 2))
            self.scene.addItem(ellipse)
            
            # 添加位置名称
            text = QGraphicsTextItem(location)
            text.setPos(x - text.boundingRect().width()/2, y + 20)
            text.setDefaultTextColor(QColor(0, 0, 0))
            font = QFont("Microsoft YaHei", 8)
            text.setFont(font)
            self.scene.addItem(text)
    
    def highlight_path(self, path):
        """高亮显示路径"""
        # 重置所有线条颜色
        for item in self.scene.items():
            if isinstance(item, QGraphicsLineItem):
                item.setPen(QPen(QColor(100, 100, 100), 2))
        
        # 高亮路径上的线条
        highlight_pen = QPen(QColor(255, 0, 0), 4)
        for i in range(len(path) - 1):
            from_loc = path[i]
            to_loc = path[i + 1]
            start_pos = QPointF(*self.campus_map.locations[from_loc])
            end_pos = QPointF(*self.campus_map.locations[to_loc])
            
            # 找到对应的线条并高亮
            for item in self.scene.items():
                if isinstance(item, QGraphicsLineItem):
                    if (abs(item.line().x1() - start_pos.x()) < 1 and 
                        abs(item.line().y1() - start_pos.y()) < 1 and
                        abs(item.line().x2() - end_pos.x()) < 1 and
                        abs(item.line().y2() - end_pos.y()) < 1):
                        item.setPen(highlight_pen)
                        break


class CampusNavigator(QMainWindow):
    def __init__(self):
        super().__init__()
        self.campus_map = CampusMap()
        self.init_ui()
    
    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle("校园新生导航系统")
        self.setGeometry(100, 100, 1200, 700)
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QHBoxLayout()
        central_widget.setLayout(main_layout)
        
        # 左侧：地图显示
        self.map_view = MapGraphicsView(self.campus_map)
        main_layout.addWidget(self.map_view, 3)
        
        # 右侧：控制面板
        control_panel = QWidget()
        control_layout = QVBoxLayout()
        control_panel.setLayout(control_layout)
        main_layout.addWidget(control_panel, 1)
        
        # 当前位置选择
        current_location_label = QLabel("当前位置:")
        current_location_label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
        control_layout.addWidget(current_location_label)
        
        self.current_location_combo = QComboBox()
        self.current_location_combo.addItems(self.campus_map.get_all_locations())
        self.current_location_combo.currentTextChanged.connect(self.on_location_changed)
        control_layout.addWidget(self.current_location_combo)
        
        # 目标功能选择
        target_function_label = QLabel("想要去:")
        target_function_label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
        control_layout.addWidget(target_function_label)
        
        self.target_function_combo = QComboBox()
        self.update_function_options()
        control_layout.addWidget(self.target_function_combo)
        
        # 查询按钮
        self.query_button = QPushButton("查询路线")
        self.query_button.setFont(QFont("Microsoft YaHei", 10))
        self.query_button.clicked.connect(self.query_route)
        control_layout.addWidget(self.query_button)
        
        # 位置功能显示
        location_info_label = QLabel("当前位置功能:")
        location_info_label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
        control_layout.addWidget(location_info_label)
        
        self.location_info_text = QTextEdit()
        self.location_info_text.setReadOnly(True)
        self.location_info_text.setMaximumHeight(100)
        control_layout.addWidget(self.location_info_text)
        
        # 路线结果显示
        route_result_label = QLabel("路线指引:")
        route_result_label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
        control_layout.addWidget(route_result_label)
        
        self.route_result_text = QTextEdit()
        self.route_result_text.setReadOnly(True)
        control_layout.addWidget(self.route_result_text)
        
        # 初始化显示
        self.on_location_changed(self.current_location_combo.currentText())
    
    def update_function_options(self):
        """更新功能选项"""
        self.target_function_combo.clear()
        
        # 获取所有位置的所有功能
        all_functions = set()
        for functions in self.campus_map.functions.values():
            all_functions.update(functions)
        
        # 添加功能选项
        self.target_function_combo.addItems(sorted(all_functions))
    
    def on_location_changed(self, location):
        """当位置改变时更新显示"""
        functions = self.campus_map.get_location_functions(location)
        if functions:
            self.location_info_text.setText(f"{location}的功能：\n" + "\n".join(f"• {func}" for func in functions))
        else:
            self.location_info_text.setText(f"{location}暂无功能信息")
    
    def query_route(self):
        """查询路线"""
        current_location = self.current_location_combo.currentText()
        target_function = self.target_function_combo.currentText()
        
        # 找到提供目标功能的位置
        target_locations = []
        for location, functions in self.campus_map.functions.items():
            if target_function in functions:
                target_locations.append(location)
        
        if not target_locations:
            self.route_result_text.setText(f"抱歉，没有找到提供'{target_function}'功能的位置")
            return
        
        # 找到最近的提供该功能的位置
        shortest_path = None
        best_target = None
        
        for target in target_locations:
            path = self.campus_map.find_shortest_path(current_location, target)
            if path:
                if shortest_path is None or len(path) < len(shortest_path):
                    shortest_path = path
                    best_target = target
        
        if shortest_path:
            description = self.campus_map.get_path_description(shortest_path)
            self.route_result_text.setText(description)
            # 在地图上高亮显示路径
            self.map_view.highlight_path(shortest_path)
        else:
            self.route_result_text.setText(f"无法找到从 {current_location} 到提供'{target_function}'功能位置的路径")


def main():
    app = QApplication(sys.argv)
    navigator = CampusNavigator()
    navigator.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
